
package com.lee.tree; 
 
import com.lee.info.CkFlowInfo; 
import com.lee.logger.Logger; 
import com.lee.utils.ArrayUtils; 
import com.lee.utils.Combination; 
import com.lee.utils.ConstantsUtils; 
import com.lee.utils.RulesUtils; 
import org.apache.commons.lang.StringUtils; 
 
import java.io.IOException; 
import java.io.Serializable; 
import java.util.*; 
import java.util.stream.Collectors; 
 
public class FrequentFound implements Serializable { 
 
 
 
    public List<TwoTuple<List<String>, Long>> findFrequentItemsetsCkflow(List<CkFlowInfo> transactions){
 
        Map<String,Long> supportItems =  new HashMap();
        Map<String,Long> items = new HashMap();
        for(CkFlowInfo transaction:transactions){
            for(String item:transaction.getCkList()){
                if(items.containsKey(item)){
                    items.put(item,items.get(item) + 1l);
                } else {
                    items.put(item,1l);
                }
            }
        }
 
        FPTree master = new FPTree();
        transactions.stream().forEach(transaction ->{
            master.add(transaction.getCkList());
        });
 
 
        //更新FPTree树
        List<TwoTuple<List<String>, Long>> itemsets =  findWithSuffix(master,transactions.size());
 
        return itemsets;
 
    }
 
    private List<TwoTuple<List<String>, Long>> findWithSuffix(FPTree tree, int total){
 
        List<TwoTuple<List<String>, Long>> freqsList = new ArrayList<>();
        Combination<String> combination = new Combination();
        //对树的所有结点遍历
        List<TwoTuple<String, List<FPNode>>> treeItems = tree.getItems();
        for(TwoTuple<String, List<FPNode>> treeItem:treeItems){
 
 
            long treeItemCount = treeItem.second.stream().mapToLong(FPNode::getCount).sum();
            if(1.0 * treeItemCount/total < ConstantsUtils.MIN_SUPPORT){
                continue;
            }
 
 
            Map<List<String>,Long> pathMap = new HashMap<>();
            for(FPNode node:treeItem.second) {
                long treeItemOneCount = node.getCount();
 
                Map<String, Long> nodeMap = new HashMap<>();
 
                long count = node.getCount();
                node = node.getParent();
                while (!node.isRoot() && node != null) {
                    String item = node.getItem();
                    if (nodeMap.containsKey(item)) {
                        nodeMap.put(node.getItem(), nodeMap.get(item) + count);
 
                    } else {
                        nodeMap.put(node.getItem(), count);
 
                    }
 
                    node = node.getParent();
                }
                ;
 
 
                List<String> nodeMapList = new ArrayList(nodeMap.keySet());
 
 
                nodeMap.put(treeItem.first, treeItemOneCount);
 
 
                for (int i = 0; i < ConstantsUtils.LEVEL; i++) {
                    List<List<String>> combinations = combination.combinations(nodeMapList, i);
                    combinations.stream().forEach(freq -> {
                        freq.add(treeItem.first);
                        //计算频繁度support
                        long support = treeItemOneCount;
 
                        freq.sort(String::compareTo);
                        if (pathMap.containsKey(freq)) {
                            pathMap.put(freq, pathMap.get(freq) + support);
                        } else {
                            pathMap.put(freq, support);
                        }
 
                    });
                }
            }
 
 
            List<TwoTuple<List<String>, Long>> freqs = new ArrayList<>();
            TwoTuple<List<String>, Long> twoTuple = new TwoTuple(Arrays.asList(treeItem.first),treeItemCount);
            freqs.add(twoTuple);
            for(List<String> item: pathMap.keySet()){
                TwoTuple<List<String>, Long> itemTwoTuple = new TwoTuple(item,pathMap.get(item));
 
                freqs.add(itemTwoTuple);
 
            };
            freqs = freqs.stream().filter(freq->{
                if(1.0 * freq.second/total >= ConstantsUtils.MIN_SUPPORT){
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
 
 
 
            freqsList.addAll(freqs);
 
        }
        return freqsList;
    }
 
} 
